#include <iostream>
#include <signal.h>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace std;

void handler(int signo)
{
	sleep(5);
	pid_t rid;
	while((rid = waitpid(-1,nullptr,WNOHANG)) > 0){
		cout << "I am a process : " << getpid() << " catch a signo : " << signo << " child quit process : " << rid << endl;
	}
}
//存在问题，如果有十个子进程同时退出，在理解中，信号捕捉期间会屏蔽该信号，那后面的信号会只有一个被接受，其他子进程并没有被等待
int main()
{
	signal(SIGCHLD,handler);
	for(int i = 0;i < 10;i++){
		pid_t id = fork();
		if(id == 0){
			while(true){
				cout << "I am a child process : " << getpid() << " ppid : " << getppid() << endl;
				sleep(1);
				break;
			}
			exit(0);
		}
		sleep(1);
	}
	while(1){
		cout << "I am a father process : " << getpid() << endl;
		sleep(1);
	}

	return 0;
}

// //volatile关键字让编译器不再对flag进行优化到寄存器中,保持内存的可见性
// volatile int flag = 1;

// void handler(int signo)
// {
// 	cout << "catch a signal : " << signo << endl;
// 	//在优化条件下，flag可能直接被优化到CPU的寄存器中:后续无需再从内存中读，就不知道他修改了
// 	flag = 0;
// }

// int main()
// {
// 	signal(2,handler);

// 	while(flag);

// 	cout << "process quit normally" << endl;
// 	return 0;
// }


//什么时候pending表由1到0  --> 在handler函数处理之前
// void printpend()
// {
// 	sigset_t pend;
// 	sigpending(&pend);
// 	for(int signo = 31;signo >= 1;signo--)
// 	{
// 		if(sigismember(&pend,signo)) cout << "1";
// 		else cout << "0";
// 	}
// 	cout << endl;
// }

// //处理时会屏蔽当前的处理信号，防止同一个函数多次执行
// void handler(int signo)
// {
// 	cout << "catch a signal : " << signo << endl;
// 	while(true)
// 	{
// 		printpend();
// 		sleep(1);
// 	}
// }

// int main()
// {
// 	struct sigaction act,oact;
// 	memset(&act,0,sizeof(act));
// 	memset(&oact,0,sizeof(oact));

// 	sigemptyset(&act.sa_mask);
// 	sigaddset(&act.sa_mask,1);
// 	act.sa_handler = handler;
// 	sigaction(SIGINT,&act,&oact);

// 	while(true)
// 	{
// 		cout << "I am a process , my pid : " << getpid() << endl;
// 		sleep(1);
// 	}
// 	return 0;
// }
